package com.glorystone.ins.controller;

import com.glorystone.ins.common.JsonResult;
import com.glorystone.ins.common.common.DataTable;
import com.glorystone.ins.common.common.PageVo;
import com.glorystone.ins.common.util.DateEnum;
import com.glorystone.ins.common.util.DateUtils;
import com.glorystone.ins.domain.*;
import com.glorystone.ins.enums.CapitalRecordStatusEnum;
import com.glorystone.ins.enums.OpponentEnum;
import com.glorystone.ins.interceptor.PageList;
import com.glorystone.ins.service.*;
import com.glorystone.ins.vo.CheckDataVO;
import com.glorystone.ins.vo.OrderQueryConditionVo;
import com.glorystone.ins.vo.ReceivableVO;
import com.glorystone.ins.vo.ReportDataVO;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 用户管理Controller
 */
@Controller
@RequestMapping("/receivable")
public class ReceivableController extends BaseController {

    @Autowired
    private IReceivableService receivableService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private CapitalRecordService capitalRecordService;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private BusinessLogService businessLogService;

    @Autowired
    private InsurerService insurerService;

    @Autowired
    private ChannelService channelService;

    /**
     * 去往应收订单管理列表
     */
    @RequestMapping("/tolist")
    @ResponseBody
    public ModelAndView tolist(ModelAndView mv, HttpServletRequest request){
        String flag = request.getParameter("initFlag");
        List<Insurer> insurerList = insurerService.selectAllInsurer();
        List<Channel> channelList = channelService.findAll();
        mv.addObject("initFlag", flag);
        mv.addObject("insurerList", insurerList);
        mv.addObject("channelList", channelList);
        mv.setViewName("receivable/receivable_list");
        return mv;
    }

    /**
     * 组装应收订单列表数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value="/queryTableData",method = RequestMethod.GET)
    @ResponseBody
    public DataTable<ReceivableVO> queryTableData(HttpServletRequest request) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        PageVo vo =  parametToPageVoData(request, ReceivableVO.class, user);
        PageList<ReceivableVO> list = receivableService.findReceivableList(vo);
        DataTable data = resultToDataTable(list);
        return data;
    }

    /**
     * 组装渠道应收订单列表数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value="/queryChannelTableData",method = RequestMethod.GET)
    @ResponseBody
    public DataTable<ReceivableVO> queryChannelTableData(HttpServletRequest request) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        PageVo vo =  parametToPageVoData(request, ReceivableVO.class, user);
        PageList<ReceivableVO> list = receivableService.queryChannelTableData(vo);
        DataTable data = resultToDataTable(list);
        return data;
    }

    /**
     * 组装应收订单核对列表数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value="/queryCheckData",method = RequestMethod.GET)
    @ResponseBody
    public DataTable<CheckDataVO> queryCheckData(HttpServletRequest request) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        PageVo vo =  parametToPageVoData(request, CheckDataVO.class, user);
        PageList<CheckDataVO> list = receivableService.findCheckDataList(vo);
        DataTable data = resultToDataTable(list);
        return data;
    }
//    /**
//     * 组装应收订单核对列表数据
//     */
//    @SuppressWarnings({ "rawtypes", "unchecked" })
//    @RequestMapping(value="/queryCheckData",method = RequestMethod.GET)
//    @ResponseBody
//    public DataTable<CheckDataVO> queryCheckData(HttpServletRequest request) {
//        String start = request.getParameter("start");
//        String length = request.getParameter("length");
//        PageList<CheckDataVO> list = new PageList<CheckDataVO>(Integer.parseInt(start)/Integer.parseInt(length)+1, Integer.parseInt(length));
//        List<CheckDataVO> aa = receivableService.queryCheckDataList();
//        Integer length2 = Integer.parseInt(start) + Integer.parseInt(length);
//        if (length2 > aa.size()) {
//            length2 = aa.size();
//        }
//        List<CheckDataVO> bb = aa.subList(Integer.parseInt(start), length2);
//        list.addAll(bb);
//        list.setTotalCount(aa.size());
//        DataTable data = resultToDataTable(list);
//        return data;
//    }

    /**
     * 上传excel（批量导入核对）
     */
    @RequestMapping("/checkBatch")
    public @ResponseBody
    JsonResult checkBatch(MultipartFile myFile, HttpServletRequest request) {
        Map<?, ?> map = null;
        String fileType = getFileType(myFile);
        if ("xlsx".equals(fileType)) {
            SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
            map = receivableService.importCheck(myFile, user.getTid());
            String status = (String) map.get("status");
            if ("0001".equals(status)) {
                return JsonResult.createSuccess(map);
            } else {
                return JsonResult.createErrorMsg(map.get("message").toString());
            }
        } else {
            return JsonResult.createErrorMsg("上传的文件格式不正确，请选择*.xlsx文件！");
        }
    }

    /**
     * 批量更新应收订单核对结果
     */
    @RequestMapping("/confirmCheck")
    public @ResponseBody
    JsonResult confirmCheck(HttpServletRequest request) {
        Map<?, ?> map = null;
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        map = receivableService.confirmCheck(user.getTid());
        String status = (String) map.get("status");
        if ("0001".equals(status)) {
            return JsonResult.createSuccessMsg(map.get("message").toString());
        } else {
            return JsonResult.createErrorMsg(map.get("message").toString());
        }
    }

    /**
     * 上传excel（批量导入开票）
     */
    @RequestMapping("/invoiceBatch")
    public @ResponseBody
    JsonResult invoiceBatch(MultipartFile myFile, HttpServletRequest request) {
        Map<?, ?> map = null;
        String fileType = getFileType(myFile);
        if ("xlsx".equals(fileType)) {
            SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
            map = receivableService.importInvoice(myFile, user.getTid());
            String status = (String) map.get("status");
            if ("0001".equals(status)) {
                return JsonResult.createSuccess(map);
            } else {
                return JsonResult.createErrorMsg(map.get("message").toString());
            }
        } else {
            return JsonResult.createErrorMsg("上传的文件格式不正确，请选择*.xlsx文件！");
        }
    }

    /**
     * 批量更新应收订单开票结果
     */
    @RequestMapping("/confirmInvoice")
    public @ResponseBody
    JsonResult confirmInvoice(HttpServletRequest request) {
        Map<?, ?> map = null;
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        map = receivableService.confirmInvoice(user.getTid());
        String status = (String) map.get("status");
        if ("0001".equals(status)) {
            return JsonResult.createSuccessMsg(map.get("message").toString());
        } else {
            return JsonResult.createErrorMsg(map.get("message").toString());
        }
    }

    /**
     * 上传excel（批量导入收款）
     */
    @RequestMapping("/gatheringBatch")
    public @ResponseBody
    JsonResult gatheringBatch(MultipartFile myFile, String gatheringDate, HttpServletRequest request) {
        Map<?, ?> map = null;
        String fileType = getFileType(myFile);
        if ("xlsx".equals(fileType)) {
            SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
            map = receivableService.importGathering(myFile, gatheringDate, user.getTid());
            String status = (String) map.get("status");
            if ("0001".equals(status)) {
                return JsonResult.createSuccess(map);
            } else {
                return JsonResult.createErrorMsg(map.get("message").toString());
            }
        } else {
            return JsonResult.createErrorMsg("上传的文件格式不正确，请选择*.xlsx文件！");
        }
    }

    /**
     * 批量更新应收订单收款结果
     */
    @RequestMapping("/confirmGathering")
    public @ResponseBody
    JsonResult confirmGathering(HttpServletRequest request) {
        Map<?, ?> map = null;
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        map = receivableService.confirmGathering(user.getTid());
        String status = (String) map.get("status");
        if ("0001".equals(status)) {
            return JsonResult.createSuccessMsg(map.get("message").toString());
        } else {
            return JsonResult.createErrorMsg(map.get("message").toString());
        }
    }

    /**
     * Excel导出应收保险公司列表
     */
    @RequestMapping("/download")
    public void exportReptileTemplet(ReceivableVO receivable, HttpServletRequest request, HttpServletResponse response) {
        String titles[] = {"序号", "出单主体", "渠道名称", "保险公司", "被保险人", "车牌号", "起保日期", "险种", "保单号", "实收保费", "保费收取时间", "签单保费", "核对签单保费", "跟单比例", "核对跟单比例", "跟单手续费", "补点比例", "核对补点比例", "补点手续费", "是否核对一致"};
        List<ReportDataVO> reportDateList = receivableService.queryReportDataList(receivable, "company");
        XSSFWorkbook workbook = receivableService.getXlsxWorkbook(titles, reportDateList, "应收保险公司订单");
        String fileName = "应收保险公司订单数据导出" + DateUtils.dateToStr(new Date(), DateEnum.DATE_BANK_SEQ);
        response.reset();
        try {
            //导出支持中文名，兼容IE、火狐
            if (request.getHeader("user-agent").indexOf("MSIE") != -1) {
                fileName = java.net.URLEncoder.encode(fileName, "utf-8") + ".xlsx";
            } else {
                fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1") + ".xlsx";
            }
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Excel导出应收渠道列表
     */
    @RequestMapping("/downloadChannel")
    public void exportChannelList(ReceivableVO receivable, HttpServletRequest request, HttpServletResponse response) {
        String titles[] = {"序号", "出单主体", "渠道名称", "保险公司", "被保险人", "车牌号", "起保日期", "险种", "保单号", "实收保费", "保费收取时间", "签单保费", "核对签单保费", "跟单比例", "核对跟单比例", "跟单手续费", "补点比例", "核对补点比例", "补点手续费", "是否核对一致"};
        List<ReportDataVO> reportDateList = receivableService.queryReportDataList(receivable, "channel");
        XSSFWorkbook workbook = receivableService.getXlsxWorkbook(titles, reportDateList, "应收渠道订单");
        String fileName = "应收渠道订单数据导出" + DateUtils.dateToStr(new Date(), DateEnum.DATE_BANK_SEQ);
        response.reset();
        try {
            //导出支持中文名，兼容IE、火狐
            if (request.getHeader("user-agent").indexOf("MSIE") != -1) {
                fileName = java.net.URLEncoder.encode(fileName, "utf-8") + ".xlsx";
            } else {
                fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1") + ".xlsx";
            }
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            workbook.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 单笔订单核对
     */
    @RequestMapping("/orderCheck")
    public @ResponseBody
    JsonResult orderCheck(long tid, BigDecimal texPremium, BigDecimal followPoint, BigDecimal replenishPoint, int checkResult, String remark, HttpServletRequest request) {
        Map<?, ?> map = null;
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        ReceivableVO receivable = new ReceivableVO();
        receivable.setTid(tid);
        receivable.setTexPremium(texPremium);
        receivable.setFollowPoint(followPoint);
        receivable.setReplenishPoint(replenishPoint);
        receivable.setCheckResult(checkResult);
        receivable.setStatus(String.valueOf(CapitalRecordStatusEnum.TO_MAKE_OUT_INVOICE.getValue()));
        receivable.setRemark(remark);
        receivable.setCheckDate(LocalDate.now());
        receivable.setUpdateBy(user.getTid());
        receivable.setUpdateDate(LocalDate.now());
        //map = receivableService.updateForOrderCheck(receivable, BusinessLog.ContentEnum.RECEIVABLE_CHECK.getValue(), remark);
        map = receivableService.doOrderCheck(receivable);
        String status = (String) map.get("status");
        if ("0001".equals(status)) {
            return JsonResult.createSuccess(map);
        } else {
            return JsonResult.createErrorMsg(map.get("message").toString());
        }
    }

    /**
     * 单笔订单开票
     */
    @RequestMapping("/orderInvoice")
    public @ResponseBody
    JsonResult orderInvoice(long tid, String invoiceDate, String remark, HttpServletRequest request) {
        Map<?, ?> map = null;
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        CapitalRecord record = receivableService.getGatheringDataById(tid);
        ReceivableVO receivable = new ReceivableVO();
        receivable.setTid(tid);
        receivable.setTicketOpenTime(LocalDate.parse(invoiceDate));
        receivable.setIsTicketOpen(1);
        receivable.setStatus(String.valueOf(CapitalRecordStatusEnum.FOR_COLLECTION.getValue()));
        receivable.setRemark(remark);
        receivable.setUpdateBy(user.getTid());
        receivable.setUpdateDate(LocalDate.now());
        receivable.setInvoiceValue(record.getFollowRpoundage().add(record.getReplenishRpoundage()));
        map = receivableService.updateForOrderCheck(receivable, BusinessLog.ContentEnum.RECEIVABLE_INVOICE.getValue(), remark);
        String status = (String) map.get("status");
        if ("0001".equals(status)) {
            return JsonResult.createSuccess(map);
        } else {
            return JsonResult.createErrorMsg(map.get("message").toString());
        }
    }

    /**
     * 单笔订单收款
     */
    @RequestMapping("/orderGathering")
    public @ResponseBody
    JsonResult orderGathering(long tid, BigDecimal realPremiumAmt, BigDecimal followRpoundage, BigDecimal replenishRpoundage, String gatheringDate, String remark, HttpServletRequest request) {
        Map<?, ?> map = null;
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        ReceivableVO receivable = new ReceivableVO();
        receivable.setTid(tid);
        receivable.setRealPremiumAmt(realPremiumAmt);
        receivable.setFollowRpoundage(followRpoundage);
        receivable.setReplenishRpoundage(replenishRpoundage);
        receivable.setReceiptDate(LocalDate.parse(gatheringDate));
        receivable.setRemark(remark);
        receivable.setUpdateBy(user.getTid());
        receivable.setUpdateDate(LocalDate.now());
        map = receivableService.checkOrderGathering(receivable);
        String status = (String) map.get("status");
        if ("0001".equals(status)) {
            return JsonResult.createSuccess(map);
        } else {
            return JsonResult.createErrorMsg(map.get("message").toString());
        }
    }

    /**
     * 获取单笔收款初始化数据
     */
    @RequestMapping("/getGatheringData")
    public @ResponseBody JsonResult getGatheringData(long tid, HttpServletRequest request) {
        Map<String, BigDecimal> map = new HashMap<String, BigDecimal>();
        try {
            CapitalRecord record = receivableService.getGatheringDataById(tid);
            map.put("mustPremiumAmt", record.getMustRebateAmt());
            map.put("followRpoundage", record.getFollowRpoundage());
            map.put("replenishRpoundage", record.getReplenishRpoundage());
            return JsonResult.createSuccess(map);
        } catch (Exception e) {
            return JsonResult.createErrorMsg("收款失败");
        }
    }

    /**
     * 应收渠道订单结算初始化数据
     */
    @RequestMapping("/getSettlementData")
    public @ResponseBody JsonResult getSettlementData(long tid, HttpServletRequest request) {
        Map<String, BigDecimal> map = new HashMap<String, BigDecimal>();
        try {
            CapitalRecord record = receivableService.getGatheringDataById(tid);
            map.put("realPremium", record.getMustPremium());
            return JsonResult.createSuccess(map);
        } catch (Exception e) {
            return JsonResult.createErrorMsg("结算失败");
        }
    }

    /**
     * 应收渠道订单结算
     */
    @RequestMapping("/orderSettlement")
    public @ResponseBody
    JsonResult orderSettlement(long tid, long channelId, BigDecimal realPremium, int capitalSourcr, String settlementDate, String remark, HttpServletRequest request) {
        Map<?, ?> map = null;
        try {
            ReceivableVO receivable = new ReceivableVO();
            receivable.setTid(tid);
            receivable.setRealPremium(realPremium);
            receivable.setReceiptDate(LocalDate.parse(settlementDate));
            receivable.setCapitalSourcr(capitalSourcr);
            receivable.setChannelId(channelId);
            receivable.setRemark(remark);
            map = receivableService.checkOrderSettlement(receivable);
            String status = (String) map.get("status");
            if ("0001".equals(status)) {
                return JsonResult.createSuccess(map);
            } else {
                return JsonResult.createErrorMsg(map.get("message").toString());
            }
        } catch (Exception e) {
            return JsonResult.createErrorMsg("结算失败");
        }
    }

    /**
     * 结算审核页面初始化数据
     */
    @RequestMapping("/toSettlementAudit")
    @ResponseBody
    public JsonResult settlementAuditOrderDetail(long ordId, int turnType, ModelAndView model) {
        Map<Object, Object> map = new HashMap();
        /**
         * 根据订单Id查询保险订单信息
         */
        OrderQueryConditionVo order = new OrderQueryConditionVo();
        order.setTid(ordId);
        Order orderInfo = orderService.selectOrderInfo(order);
        map.put("orderInfo", orderInfo);
        map.put("turnType", turnType);
        /**
         * 根据订单Id查询保险资金流水信息
         */
        List<ReceivableVO> recordList = receivableService.queryOrderCapitalRecord(order);
        if (recordList != null) {
            for (ReceivableVO record : recordList) {
                if (OpponentEnum.CHANNEL.getValue() == Integer.parseInt(record.getOpponent())) {
                    map.put("channelRecord", record);
                } else if (OpponentEnum.INSURANCECOMPANY.getValue() == Integer.parseInt(record.getOpponent())) {
                    map.put("companyRecord", record);
                }
            }
        }
        List<BusinessLog> optionList = businessLogService.findList(BusinessLog.BusinessTypeEnum.ORDER, order.getTid());
        map.put("optionList", optionList);
        return JsonResult.createSuccess(map);
    }

    /**
     * 结算审核
     */
    @RequestMapping("/settlementAudit")
    public @ResponseBody JsonResult settlementAudit(long tid, String auditOpinion, String auditType, HttpServletRequest request) {
        try {
            Map<?, ?> map = null;
            SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
            String executeType = null;
            ReceivableVO receivable = new ReceivableVO();
            if ("adopt".equals(auditType)) {
                receivable.setTid(tid);
                receivable.setStatus(String.valueOf(CapitalRecordStatusEnum.SETTLED.getValue()));
                receivable.setRemark(auditOpinion);
                executeType = BusinessLog.ContentEnum.RECEIVABLE_SETTLEMENT_AUDIT_ADOPT.getValue();
            } else if ("reject".equals(auditType)) {
                receivable.setTid(tid);
                receivable.setRealPremiumAmt(new BigDecimal("0"));
                receivable.setStatus(String.valueOf(CapitalRecordStatusEnum.SETTLEMENT_AUDIT_REJECT.getValue()));
                receivable.setRemark(auditOpinion);
                executeType = BusinessLog.ContentEnum.RECEIVABLE_SETTLEMENT_AUDIT_REJECT.getValue();
            }
            receivable.setUpdateBy(user.getTid());
            receivable.setUpdateDate(LocalDate.now());
            map = receivableService.updateForOrderCheck(receivable, executeType, auditOpinion);
            return JsonResult.createSuccess(map);
        } catch (Exception e) {
            return JsonResult.createErrorMsg("审核提交失败");
        }
    }

    /**
     * 应收订单退保初始化
     * @param capitalId 资金流水表tid
     * @param ordId 订单表tid
     */
    @RequestMapping("/checkSurrenderData")
    public @ResponseBody JsonResult checkSurrenderData(long capitalId, long ordId, HttpServletRequest request) {
        Map<String, String> map = new HashMap<String, String>();
        try {
            ReceivableVO receivable = receivableService.getReceivableForSurrender(capitalId);
            CapitalRecord channelRecord = receivableService.getChannelCapitalRecordByOrderId(ordId);
            if (channelRecord != null) {
                map.put("channelFlag", "1");
                map.put("channelStatus", String.valueOf(channelRecord.getStatus()));
            } else {
                map.put("channelFlag", "0");
                map.put("channelStatus", "0");
            }
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            map.put("insureStartDate", dtf.format(receivable.getDatePolicy()));
            return JsonResult.createSuccess(map);
        } catch (Exception e) {
            return JsonResult.createErrorMsg("退保初始化失败");
        }
    }

    /**
     * 应收订单退保
     * @param receivable 资金流水
     */
    @RequestMapping("/orderSurrender")
    @ResponseBody
    public JsonResult orderSurrender(ReceivableVO receivable, HttpServletRequest request) {
        Map<?, ?> map = null;
        try {
            CapitalRecord record = receivableService.getGatheringDataById(receivable.getTid());
            map = receivableService.orderSurrender(record, receivable);
            String status = (String) map.get("status");
            if ("0001".equals(status)) {
                return JsonResult.createSuccessMsg(map.get("message").toString());
            } else {
                return JsonResult.createErrorMsg(map.get("message").toString());
            }
        } catch (Exception e) {
            return JsonResult.createErrorMsg("退保初始化失败");
        }
    }

    //通过数据流获取文件格式
    public String getFileType(MultipartFile myFile) {
        String fileType = null;
        InputStream inputStream = null;
        try {
            CommonsMultipartFile cFile = (CommonsMultipartFile) myFile;
            DiskFileItem fileItem = (DiskFileItem) cFile.getFileItem();
            inputStream = fileItem.getInputStream();
            fileType = receivableService.getTypeByStream(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileType;
    }

} 
